﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;

namespace Workflows.Components.TextMining.Collapse
{
    /// <summary>
    /// 
    /// </summary>
    public class DateComparer:IAttributeComparer
    {
        #region IAttributeComparer Members

        /// <summary>
        /// specify either use code snippet or class
        /// </summary>
        public AttributeComparerType ComparerType
        {
            get
            {
                return AttributeComparerType.ClassComparer;
            }
        }

        private SqlDbType _FieldDbType;
        public SqlDbType FieldDbType
        {
            get { return _FieldDbType; }
            set { _FieldDbType=value; }
        }

        /// <summary>
        /// default compare method
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <param name="unevenDistTableName"></param>
        /// <returns></returns>
        public double Compare(object value1, object value2, double penalty, SqlConnection conn, string unevenDistTableName)
        {
            if (value1 == null || value2 == null || value1 == DBNull.Value || value2 == DBNull.Value 
                || value1.ToString().Length == 0 || value2.ToString().Length == 0)
                return 0.0;

            DateTime date1 = DateTime.Parse(value1.ToString());
            DateTime date2 = DateTime.Parse(value2.ToString());
            if (date1 == date2)
                return 1.00;
            else
            {
                if (new TimeSpan(Math.Abs(date1.Ticks - date2.Ticks)).Days == 1)
                {
                    return 0.80;
                }
                else if (date1.Year == date2.Year && date1.Day == date2.Day)
                {
                    if (Math.Abs(date1.Month - date2.Month) == 1)
                        return 0.75;
                }
                else if (date1.Month == date2.Month && date1.Day == date2.Day)
                {
                    if (Math.Abs(date1.Year - date2.Year) == 1)
                        return 0.70;
                }

                string dateStr1 = date1.Year.ToString() +
                                  (date1.Month >= 10 ? date1.Month.ToString() : "0" + date1.Month.ToString()) +
                                  (date1.Day >= 10 ? date1.Day.ToString() : "0" + date1.Day.ToString());
                string dateStr2 = date2.Year.ToString() +
                                  (date2.Month >= 10 ? date2.Month.ToString() : "0" + date2.Month.ToString()) +
                                  (date2.Day >= 10 ? date2.Day.ToString() : "0" + date2.Day.ToString());
                char[] dateChar1 = dateStr1.ToCharArray();
                char[] dateChar2 = dateStr2.ToCharArray();
                List<int> mismatchedPositions = new List<int>();
                BitArray bits = new BitArray(dateChar1.Length);
                bits.SetAll(true);
                for (int i = 0; i < bits.Length; i++)
                {
                    if (dateChar1[i] != dateChar2[i])
                    {
                        bits[i] = false;
                        mismatchedPositions.Add(i);
                    }
                }
                if (mismatchedPositions.Count == 1)
                {
                    return 0.65;
                }
                else if (mismatchedPositions.Count == 2)
                {
                    char firstChar1 = dateChar1[mismatchedPositions[0]];
                    char firstChar2 = dateChar2[mismatchedPositions[0]];
                    char secondChar1 = dateChar1[mismatchedPositions[1]];
                    char secondChar2 = dateChar2[mismatchedPositions[1]];
                    if (firstChar1 == secondChar2 && firstChar2 == secondChar1)
                        return 0.60;
                }
                return penalty;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="unevenDistTableName"></param>
        /// <returns></returns>
        public object Merge(List<object> values, SqlConnection conn, string unevenDistTableName)
        {
            if(values ==null || values.Count==0)
                return null;

            Dictionary<DateTime,int> countByDate=new Dictionary<DateTime, int>();
            foreach(object obj in values)
            {
                if(obj.GetType()==typeof(DateTime))
                {
                    DateTime date = (DateTime) obj;
                    if(countByDate.ContainsKey(date))
                    {
                        int count = countByDate[date];
                        count++;
                        countByDate[date] = count;
                    }
                    else
                    {
                        countByDate.Add(date,1);
                    }
                }
            }
            if(countByDate.Count==0)
            {
                return null;
            }
            else if(countByDate.Count==1)
            {
                DateTime[] dates=new DateTime[countByDate.Count];
                countByDate.Keys.CopyTo(dates,0);
                return dates[0];
            }
            else 
            {
                DateTime[] dates = new DateTime[countByDate.Count];
                countByDate.Keys.CopyTo(dates, 0);
                DateTime topDateByCount = dates[0];
                DateTime secondTopDateByCount = dates[1];
                DateTime tmp;
                if(countByDate[topDateByCount]<countByDate[secondTopDateByCount])
                {
                    tmp = topDateByCount;
                    topDateByCount = secondTopDateByCount;
                    secondTopDateByCount = tmp;
                }
                if(countByDate.Count>2)
                {
                    for(int i=2;i<countByDate.Count;i++)
                    {
                        tmp = dates[i];
                        if(countByDate[tmp]>countByDate[secondTopDateByCount])
                        {
                            if(countByDate[tmp]>countByDate[topDateByCount])
                            {
                                secondTopDateByCount = topDateByCount;
                                topDateByCount = tmp;
                            }
                            else
                            {
                                secondTopDateByCount = tmp;
                            }
                        }
                    }
                }
                bool tied = false;
                if(countByDate[topDateByCount]==countByDate[secondTopDateByCount])
                {
                    tied = true;
                }
                if(tied)
                {
                    if(topDateByCount.Year >=1950 && topDateByCount.Year <=1975)
                        return topDateByCount;
                    else if (secondTopDateByCount.Year >= 1950 && secondTopDateByCount.Year <= 1975)
                        return secondTopDateByCount;
                    else
                        return topDateByCount;
                }
                else
                {
                    return topDateByCount;
                }
            }
        }
        #endregion

        #region dist frequency
        private int GetFrequencyForValue(SqlConnection conn, string distTableName, string fieldValue)
        {
            return 0;
        }
        #endregion
    }
}
